package controller;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;

import javax.swing.JOptionPane;
import javax.swing.JPanel;

import ui.BusyDialog;
import model.BuyControlIterface;
import model.Database;
import model.IOFile;
import model.OptionMessenger;
import model.Partner;
import model.SellTableModel;
import view.SellPanel;

public class SellController implements ActionListener, BuyControlIterface {
	private NumberFormat numFormat;
	private SellTableModel tableModel;
	private SellPanel view;
	private int id;
	private DateFormat dateFormat;
	private double sumMoney;
	private int sumTax;
	private int sumAmount;

	public SellController(SellTableModel tableModel) {
		this.tableModel = tableModel;
		this.view = new SellPanel(tableModel, this, true);
		this.numFormat = NumberFormat.getNumberInstance();
		this.numFormat.setMinimumFractionDigits(0);
		this.numFormat.setMaximumFractionDigits(4);
		this.dateFormat = new SimpleDateFormat("yyy-MM-dd");
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		String cmd = e.getActionCommand();
		view.stopCellEditing();
		switch (cmd) {
		case "add":
			add();
			break;
		case "ref":
			refresh();
			break;
		case "del":
			delete();
			break;
		case "comp":
			computing();
			break;
		case "save":
			if (view.checkBill() && view.checkPartner()) {
				if (tableModel.checkCellNull())
					OptionMessenger
							.showMessageDialog(
									OptionMessenger.windowForComponent(view),
									"Nhập thiếu trường dữ liệu, vui lòng nhập đầy đủ thông tin",
									"Cảnh báo lỗi",
									OptionMessenger.ERROR_MESSAGE);
				else {
					ActionListener action = new ActionListener() {

						@Override
						public void actionPerformed(ActionEvent e) {
							try {
								getMaxIDDetail();
								// if (!view.checkPartner())
								SellController.this.createPartner(view
										.getPartner());
								tableModel.saveDeviceList(id, view.getDate());
								computing();
								SellController.this.createBill(id,
										view.getPartner());
							} catch (ClassNotFoundException | SQLException e1) {
								e1.printStackTrace();
							}

						}
					};
					BusyDialog.showBusyDialog(
							OptionMessenger.windowForComponent(view),
							"Đang lưu dữ liệu", action, null);
					OptionMessenger.showMessageDialog(
							OptionMessenger.windowForComponent(view),
							"Dữ liệu đã được lưu", "Thông báo",
							OptionMessenger.INFORMATION_MESSAGE);
				}
			}
			break;
		case "new":
			int answer = OptionMessenger
					.showQuestionDialog(
							OptionMessenger.windowForComponent(view),
							"Các thông tin trong hóa đơn nếu chưa lưu sẽ bị mất\nTiếp tục?",
							"Cảnh báo", OptionMessenger.QUESTION_MESSAGE);
			if (answer == OptionMessenger.OK_OPTION) {
				view.deleteAll();
				tableModel.refreshData();
			}
			break;
		}
	}

	protected void createBill(int id, Partner partner) {
		Connection connect = null;
		try {
			connect = Database.connect();
			PreparedStatement pre = connect
					.prepareStatement("INSERT INTO bill(type, date, id_partner, id_detailbill, id_employee, "
							+ "sum_amount, sum_money, sum_tax, money_payment, payment) VALUES(?,?,?,?,?,?,?,?,?,?)");
			pre.setString(1, "Sell");
			pre.setString(2, dateFormat.format(view.getDate()));
			pre.setInt(3, partner.getId());
			pre.setInt(4, id);
			pre.setInt(5, view.getEmployee().getId());
			pre.setInt(6, sumAmount);
			pre.setDouble(7, sumMoney);
			pre.setDouble(8, sumTax);
			pre.setDouble(9, sumTax + sumMoney);
			pre.setString(10, view.getPayment());

			pre.executeUpdate();
		} catch (ClassNotFoundException e) {
			e.printStackTrace(IOFile.getInstance());
		} catch (SQLException e) {
			e.printStackTrace(IOFile.getInstance());
		}
	}

	protected void createPartner(Partner p) {
		Connection connection = null;
		try {
			connection = Database.connect();
			PreparedStatement pre = connection
					.prepareStatement("INSERT INTO partner(customer, name, address, phone, fax, email, note) VALUES(?,?,?,?,?,?,?)");
			pre.setInt(1, 1); // customer
			pre.setString(2, p.getName());
			pre.setString(3, p.getAddress());
			pre.setString(4, p.getPhone());
			pre.setString(5, p.getFax());
			pre.setString(6, p.getEmail());
			pre.setString(7, p.getNote());

			pre.executeUpdate();
		} catch (ClassNotFoundException e) {
			e.printStackTrace(IOFile.getInstance());
		} catch (SQLException e) {
			e.printStackTrace(IOFile.getInstance());
		} finally {
			if (connection != null)
				try {
					connection.close();
				} catch (SQLException e) {
					e.printStackTrace(IOFile.getInstance());
				}
		}

	}

	public void add() {
		if (!tableModel.isEmpty()) {
			if (tableModel.checkCellNull()) {
				JOptionPane
						.showMessageDialog(
								view,
								"Nhập thiếu trường dữ liệu, vui lòng nhập đầy đủ thông tin",
								"Cảnh báo lỗi", JOptionPane.ERROR_MESSAGE);
				return;
			}
		}
		tableModel.addNullRow();
	}

	public void delete() {
		int[] rows = view.getSelectedRows();
		if (rows.length == 0) {
			JOptionPane.showMessageDialog(view, "Vui lòng chọn dòng cần xóa",
					"Cảnh báo", JOptionPane.WARNING_MESSAGE);
		} else if (JOptionPane.showConfirmDialog(view,
				"Bạn có chắc muốn xóa các dòng hiện tại",
				"Xác nhận xóa thông tin", JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION) {
			for (int i = rows.length - 1; i > -1; i--) {
				tableModel.deleteRow(rows[i]);
			}
			if (tableModel.isEmpty())
				tableModel.addNullRow();
			else {
				tableModel.numberCount();
				tableModel.fireTableDataChanged();
			}
		}
	}

	public void refresh() {
		if (tableModel.isEmpty()) {
			JOptionPane.showMessageDialog(view, "Hiện tại chưa có dữ liệu!",
					"Lỗi", JOptionPane.ERROR_MESSAGE);
		} else if (JOptionPane
				.showConfirmDialog(
						view,
						"Tất cả dữ liệu đã nhập hiện tại sẽ bị mất\nBạn có muốn làm mới danh sách dữ liệu?",
						"Xác nhận", JOptionPane.WARNING_MESSAGE) == JOptionPane.OK_OPTION) {
			tableModel.clearData();
			tableModel.addNullRow();
		}
	}

	public void computing() {
		if (!tableModel.checkCellNull()) {
			sumMoney = 0;
			sumTax = 0;
			sumAmount = 0;
			try {
				int amountIndex = tableModel.findColumn("số lượng");
				int billIndex = tableModel.findColumn("đơn giá");
				int thueIndex = tableModel.findColumn("thuế suất (%)");

				int sl = 0;
				double donGia;
				double thue;

				for (int i = 0; i < tableModel.getRowCount(); i++) { // rows
					sl = (int) tableModel.getValueAt(i, amountIndex);
					donGia = (double) tableModel.getValueAt(i, billIndex);
					thue = (double) tableModel.getValueAt(i, thueIndex);
					sumAmount += sl;
					sumMoney += (sl * donGia);
					sumTax += ((thue / 100) * donGia * sl);
				}
				view.setValue(numFormat.format(sumMoney), numFormat.format(sl),
						numFormat.format(sumTax),
						numFormat.format(sumMoney + sumTax));
			} catch (NumberFormatException e) {
				JOptionPane.showMessageDialog(
						OptionMessenger.windowForComponent(view),
						"Định dạng số không hợp lệ", "Lỗi",
						JOptionPane.ERROR_MESSAGE);
			} catch (Exception e) {
				e.printStackTrace(IOFile.getInstance());
				JOptionPane.showMessageDialog(
						OptionMessenger.windowForComponent(view), "Ngoại lệ: "
								+ e.getMessage());
			}
		} else {
			OptionMessenger
					.showMessageDialog(
							OptionMessenger.windowForComponent(view),
							"Nhập thiếu thông tin trường dữ liệu\nVui lòng nhập dữ liệu đầy đủ các cột",
							"Lỗi", JOptionPane.ERROR_MESSAGE);
		}
	}

	@Override
	public boolean processer() {
		if (!tableModel.checkCellNull()) {
			double sumMoney = 0, sumThue = 0;
			try {
				int amountIndex = tableModel.findColumn("số lượng");
				int billIndex = tableModel.findColumn("đơn giá");
				int thueIndex = tableModel.findColumn("thuế suất (%)");

				int sl = 0;
				double donGia;
				double thue;
				int tongSL = 0;

				for (int i = 0; i < tableModel.getRowCount(); i++) { // rows
					sl = (int) tableModel.getValueAt(i, amountIndex);
					tongSL += sl;
					donGia = (double) tableModel.getValueAt(i, billIndex);
					thue = (double) tableModel.getValueAt(i, thueIndex);
					sumMoney += (sl * donGia);
					sumThue += ((thue / 100) * donGia * sl);
				}
				view.setValue(numFormat.format(tongSL),
						numFormat.format(sumThue), numFormat.format(sumMoney),
						numFormat.format(sumThue + sumMoney));
				return true;
			} catch (NumberFormatException e) {
				OptionMessenger.showMessageDialog(
						OptionMessenger.windowForComponent(view),
						"Định dạng số không hợp lệ", "Lỗi",
						OptionMessenger.ERROR_MESSAGE);
			} catch (Exception e) {
				e.printStackTrace(IOFile.getInstance());
				OptionMessenger.showMessageDialog(
						OptionMessenger.windowForComponent(view),
						"Xuất hiện lỗi trong lúc thực thi, chi tiết: "
								+ e.getMessage(), "Ngoại lệ",
						OptionMessenger.ERROR_MESSAGE);
			}
		}
		return false;
	}

	public void createDetailBill() {
		Connection connect = null;
		try {
			connect = Database.connect();
			PreparedStatement pre = connect
					.prepareStatement("INSERT INTO detailbill VALUES(?,?,?)");

			pre.setInt(1, id);

			int deviceIndex = tableModel.findColumn("mã hàng");
			int amountIndex = tableModel.findColumn("số lượng");
			for (int i = 0; i < tableModel.getRowCount(); i++) {
				ArrayList<Object> list = tableModel.getRowAt(i);
				pre.setString(2, (String) list.get(deviceIndex));
				pre.setInt(3, (int) list.get(amountIndex));
				System.out.println(pre);
				pre.executeUpdate();
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace(IOFile.getInstance());
		} catch (SQLException e) {
			e.printStackTrace(IOFile.getInstance());
		} finally {
			if (connect != null)
				try {
					connect.close();
				} catch (SQLException e) {
					e.printStackTrace(IOFile.getInstance());
				}
		}
	}

	public int getMaxIDDetail() {
		Connection connect = null;
		try {
			connect = Database.connect();
			PreparedStatement pre = connect
					.prepareStatement("SELECT max(id_detail) + 1 FROM detailbill");
			ResultSet rs = pre.executeQuery();

			if (rs.first()) {
				this.id = rs.getInt(1);
			} else {
				this.id = 0;
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace(IOFile.getInstance());
		} catch (SQLException e) {
			e.printStackTrace(IOFile.getInstance());
		} finally {
			if (connect != null)
				try {
					connect.close();
				} catch (SQLException e) {
					e.printStackTrace(IOFile.getInstance());
				}
		}
		return this.id;

	}

	public JPanel getView() {
		return this.view;
	}

}
